package top.gytf.unifiedcall.common.support;

import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import top.gytf.unifiedcall.common.api.ApiDefinition;
import top.gytf.unifiedcall.common.api.ApiDefinitionFactory;
import top.gytf.unifiedcall.common.contract.ApiContractManager;
import top.gytf.unifiedcall.common.detial.UnifiedCallPackageManager;
import top.gytf.unifiedcall.model.contract.ApiContract;
import top.gytf.unifiedcall.model.detail.UnifiedCallPackageDetail;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Objects;

/**
 * API定义工厂的通用实现
 */
@RequiredArgsConstructor
public class ApiDefinitionFactoryImpl implements ApiDefinitionFactory {
    private final ApiContractManager apiContractManager;
    private final UnifiedCallPackageManager unifiedCallPackageManager;

    @Override
    public ApiDefinition create(Method apiMethod) {
        return SimpleApiDefinition.builder()
                .packageDetail(unifiedCallPackageManager.findByApiMethod(apiMethod)
                        .orElseThrow(() -> new IllegalArgumentException("UnifiedCallPackageDetail not found for method: " + apiMethod)))
                .apiClient(apiMethod.getDeclaringClass())
                .apiMethod(apiMethod)
                .returnType(apiMethod.getReturnType())
                .apiContracts(apiContractManager.findContracts(apiMethod, true))
                .build();
    }

    /**
     * 通用的响应基本信息
     */
    @Getter
    @Builder
    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
    public static class SimpleApiDefinition implements ApiDefinition {
        private final UnifiedCallPackageDetail packageDetail;
        private final Class<?> apiClient;
        private final Method apiMethod;
        private final Class<?> returnType;
        private final List<ApiContract> apiContracts;

        @Override
        public <T extends ApiContract> List<T> getApiContracts(Class<T> requiredContractClass) {
            return getApiContracts().stream()
                    .filter(requiredContractClass::isInstance)
                    .map(requiredContractClass::cast)
                    .toList();
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {return true;}
            if (!(o instanceof SimpleApiDefinition that)) {return false;}
            return Objects.equals(getApiClient(), that.getApiClient()) && Objects.equals(getApiMethod(), that.getApiMethod());
        }

        @Override
        public int hashCode() {
            return Objects.hash(getApiClient(), getApiMethod());
        }
    }

}
